/**
 * Copyright (C) 2007 Mustafa K. Isik - isik@acm.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

package com.paxcodi.sockets.rpc;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer implements Runnable {

    private ServerSocket listenServerSocket;

    SimpleServer(int port) throws IOException {
	listenServerSocket = new ServerSocket(port);
	System.out.println("Listening for connections on port " + port);
    }

    /**
     * Loops listening for service requests.
     * 
     * Stops listening upon receiving the "SHUTDOWN" string/command.
     */
    public void run() {
	while(true) {
	    //read from input
	    Socket listenSocket = null;
	    try {
		listenSocket = listenServerSocket.accept();

		InputStream routeFromRemote = 
		    new BufferedInputStream(listenSocket.getInputStream());//in bytes
		InputStreamReader unbufferedReadFromRemote = 
		    new InputStreamReader(routeFromRemote); //in characters, unbuff.
		BufferedReader readFromRemote = 
		    new BufferedReader(unbufferedReadFromRemote); //in chars, buff.

		OutputStream routeToRemote = 
		    new BufferedOutputStream(listenSocket.getOutputStream());
		OutputStreamWriter writeToRemote = 
		    new OutputStreamWriter(routeToRemote);

		String command = readFromRemote.readLine();

		if(command.equalsIgnoreCase("ADD")){
		    //protocol asks for two more parameters, ignore the rest
		    int number1 = Integer.parseInt(readFromRemote.readLine());
		    int number2 = Integer.parseInt(readFromRemote.readLine());
		    System.out.println("adding numbers " + number1 + 
			    " " + number2);
		    int sum = number1 + number2;
		    System.out.println("sending result " + sum + " back.");
		    writeToRemote.write(sum + "\n");
		    writeToRemote.flush();
		} else if(command.equalsIgnoreCase("SHUTDOWN")) {
		    System.out.println("shutting down");
		    break;
		} else {
		    //this is the case where the input string is supposed to
		    //be capitalized and returned
		    String toBeCapitalized = command.toUpperCase();//use default locale
		    System.out.println("sending capitalized version " + 
			    toBeCapitalized + " of " + command + " back.");
		    writeToRemote.write(toBeCapitalized);
		    writeToRemote.flush();
		}

	    } catch (IOException e) {
		System.err.println(e);
	    } finally {
		if(!(listenSocket == null))
		    try {
			listenSocket.close();
		    } catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		    }
	    }
	    //perform appropriate processing

	    //write to output
	}

    }

    /**
     * @param args port to be listened on
     */
    public static void main(String[] args) {
	if(args.length != 1) {
	    System.err.println("usage: java SimpleServer <port-to-listen-on>" );
	    return;
	}
	int listenOnPort = Integer.parseInt(args[0]);
	//start a server on port provided via commandline
	try {
	    SimpleServer server = new SimpleServer(listenOnPort);
	    new Thread(server).start();
	} catch(IOException e) {
	    System.err.println("There seems to be a server already " +
		    "running on port " + listenOnPort + ".\n" + e);
	}

    }

}
